/*
 * Quercia Luciano
 * Algoritmi e Strutture Dati
 * a.a. 2009-10
 */


#ifndef _PILA_H_
#define _PILA_H_


#define SIZE 100

#include "nodoP.h"

template <class T>
class Pila {
public:
	Pila();
	~Pila();

	//operatori
	bool pilaVuota() const;
	void inPila(T elem)         throw (char const *);
	void fuoriPila()            throw (char const *);
	T leggiPila()		        throw (char const *);

	//metodi personalizzati
	void print(void);
	void printAll(void);

private:

	typedef int posizione;
	posizione top;

	NodoP<T> vettore[ SIZE ];
};



/*****************************
 *        DEFINIZIONI        *
 *     dei metodi di Pila    *
 *****************************/


template <class T>
Pila<T>::Pila() {
	top = 0 ;
}



template <class T>
Pila<T>::~Pila() {}



template <class T>
bool Pila<T>::pilaVuota() const {
	return (top == 0);
}



template <class T>
void Pila<T>::inPila(T elem) throw (char const *) {
	if (top < SIZE -1) {
		vettore[top].setValue(elem);
		top++ ;
	} else {
		throw "Buffer overflow";
	}
}


template <class T>
void Pila<T>::fuoriPila() throw (char const *) {
	if ( !pilaVuota() ) {
		top--;
	}
	else
		throw "Impossibile cancellare da una Pila vuota" ;
}


template <class T>
T Pila<T>::leggiPila() throw (char const *) {
	if ( !pilaVuota() )
		return vettore[ top -1 ].getValue();
	else
		throw "Impossibile leggere da una Pila vuota";
}




template <class T>
void Pila<T>::print(void) {
	if ( ! pilaVuota() ) {
		cout << "[ " << leggiPila() << " ]" << endl ;
	} else
		cout << "[ Empty Stack ]" << endl ;
}

template <class T>
void Pila<T>::printAll(void) {
	if ( ! pilaVuota() ) {
		cout << "[ " ;
		for (int i=top-1; i>=0; i--)
			cout << vettore[i].getValue() << " " ;
		cout << "]" << endl ;
	} else
		cout << "[ Empty Stack ]" << endl ;
}

#endif
